package main

import (
	"fmt"
	"log"
	"math/rand"
	"sync"
	"time"
)

type MonitoringSystem struct {
	metricChan       chan *Metric
	alertChan        chan *Alert
	notificationChan chan *Notification

	rules []*AlertRule
	wg    sync.WaitGroup
}

type Alert struct {
	Rule      *AlertRule
	Metric    *Metric
	Timestamp time.Time
}

type Metric struct {
	ServerID    string
	CPUUsage    float64
	MemoryUsage float64
	DiskUsage   float64
	Timestamp   time.Time
}

type AlertRule struct {
	ID        string
	Condition func(*Metric) bool
	Message   string
	Severity  string
}
type Notification struct {
	Alert   *Alert
	Method  string // email, sms, webhook
	Message string
}

func NewMonitoringSystem() *MonitoringSystem {
	return &MonitoringSystem{
		metricChan:       make(chan *Metric, 5000),
		alertChan:        make(chan *Alert, 1000),
		notificationChan: make(chan *Notification, 1000),
		rules: []*AlertRule{
			{
				ID: "high_cpu",
				Condition: func(m *Metric) bool {
					return m.CPUUsage > 80.0
				},
				Message:  "CPU使用率过高",
				Severity: "warning",
			},
			{
				ID: "high_memory",
				Condition: func(m *Metric) bool {
					return m.MemoryUsage > 90.0
				},
				Message:  "内存使用率过高",
				Severity: "critical",
			},
		},
	}
}

func (m *MonitoringSystem) Start() {
	// 启动指标处理worker
	for i := 0; i < 10; i++ {
		go m.metricProcessor(i)
	}

	// 启动告警处理worker
	for i := 0; i < 5; i++ {
		go m.alertProcessor(i)
	}

	// 启动通知发送worker
	for i := 0; i < 3; i++ {
		go m.notificationProcessor(i)
	}
}

func (m *MonitoringSystem) ReceiveMetric(metric *Metric) {
	m.wg.Add(1)
	m.metricChan <- metric
}

func (m *MonitoringSystem) metricProcessor(workerID int) {
	for metric := range m.metricChan {
		// 检查所有告警规则
		for _, rule := range m.rules {
			if rule.Condition(metric) {
				alert := &Alert{
					Rule:      rule,
					Metric:    metric,
					Timestamp: time.Now(),
				}
				m.alertChan <- alert
			}
		}
		m.wg.Done()
	}
}

func (m *MonitoringSystem) alertProcessor(workerID int) {
	for alert := range m.alertChan {
		// 处理告警
		notification := &Notification{
			Alert:  alert,
			Method: "email",
			Message: fmt.Sprintf("[%s] 服务器%s: %s - 当前值: %.2f",
				alert.Rule.Severity, alert.Metric.ServerID,
				alert.Rule.Message, getMetricValue(alert)),
		}

		m.notificationChan <- notification
	}
}

func (m *MonitoringSystem) notificationProcessor(workerID int) {
	for notification := range m.notificationChan {
		// 模拟发送通知
		time.Sleep(50 * time.Millisecond)
		log.Printf("Worker%d发送通知: %s", workerID, notification.Message)
	}
}

func getMetricValue(alert *Alert) float64 {
	switch alert.Rule.ID {
	case "high_cpu":
		return alert.Metric.CPUUsage
	case "high_memory":
		return alert.Metric.MemoryUsage
	default:
		return 0
	}
}

func main() {
	monitor := NewMonitoringSystem()
	monitor.Start()

	// 模拟1000台服务器发送指标
	servers := generateServers(1000)

	// 每台服务器发送10次指标
	for i := 0; i < 10; i++ {
		for _, server := range servers {
			metric := &Metric{
				ServerID:    server,
				CPUUsage:    rand.Float64() * 100,
				MemoryUsage: rand.Float64() * 100,
				DiskUsage:   rand.Float64() * 100,
				Timestamp:   time.Now(),
			}
			monitor.ReceiveMetric(metric)
		}
		time.Sleep(1 * time.Second)
	}

	monitor.wg.Wait()
	close(monitor.metricChan)
	close(monitor.alertChan)
	close(monitor.notificationChan)

	time.Sleep(2 * time.Second)
}

func generateServers(count int) []string {
	var servers []string
	for i := 0; i < count; i++ {
		servers = append(servers, fmt.Sprintf("server-%04d", i))
	}
	return servers
}
